﻿using System;
using System.Drawing;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using BrainTechLLC;
using BrainTechLLC.ImageOperatorsNonAForgeDependent;
using BrainTechLLC.WPF;
using ImageAppDataModels;
using ImageAppViewModels;
using System.ComponentModel;
using BrainTechLLC.FilterExtensions;
using System.IO;
using System.Threading;
using BrainTechLLC.ThreadSafeObjects;
using System.Diagnostics;
using System.Collections.Generic;
using VirtualizingTilePanelSample;

namespace WpfImageDuplicates
{
    /// <summary>
    /// Interaction logic for ThumbnailView.xaml
    /// </summary>
    public partial class ThumbnailView : UserControl, INotifyPropertyChanged, IVirtualizedCreated
    {
        public event EventHandler SetThumbImage;
        public event EventHandler ThumbVisibilityChanged;
        public bool _isWired;
        public bool _noGood;
        public bool _definitelyNotVisible;
        public bool _definitelyVisible;
        public bool _sameAsLastTimeVisible;
        public DateTime _LastVisible;
        protected bool _thumbVisible;
        protected ThumbViewDebug ThumbDebug;
        public FileImageViewModel _vm;
        public TextBlock _tb;
        protected bool _IsSelected;
        public ImageCollectionView _parentCollectionView;
        public System.Windows.Point _lastPositionInScroller;
        public System.Windows.Point PointMouseDown;

        public bool IsSelected
        {
            get { return _vm == null ? false : _vm.IsSelected; }
            set
            {
                if (_vm != null && _vm.IsSelected != value)
                {
                    _vm.IsSelected = value;
                    if (value)
                    {
                        this.ParentCollectionView.lstItems.SelectedItems.Add(_vm);
                    }
                    else
                    {
                        this.ParentCollectionView.lstItems.SelectedItems.Remove(FileImageViewModel);
                    }
                    OnPropertyChanged("IsSelected");
                }
            }
        }

        static Thread t;
        static ThreadSafeQueue<PassedInfoToCreateImageSource> WorkQueue = new ThreadSafeQueue<PassedInfoToCreateImageSource>();

        static ThumbnailView()
        {
            ThreadStart ts = new ThreadStart(ProcessCreateImageSource);
            t = ts.CreateAndRunThread(true);
            t.Name = "ThumbnailViewProcessCreateImageSource";
            //t.Priority = ThreadPriority.AboveNormal;
        }

        static void ProcessCreateImageSource()
        {
            while (true)
            {
                PassedInfoToCreateImageSource info;
                bool doneAnything = false;
                while (WorkQueue.Dequeue(out info))
                {
                    var vm = info.ThumbnailView._vm;
                    if (vm != null)
                    {
                        FileImage fi = vm.FileImage as FileImage;
                        //Console.WriteLine("Create Image Source: " + fi.FileName);
                        SingleThumbnail thumb = fi.ThumbnailObject;
                        if (thumb == null)
                        {
                            fi.GetThumbnail(LoadOptions.LoadSync, (f, t) => info.ThumbnailView.SetThumb(f.ThumbnailCached));
                            thumb = fi.ThumbnailObject;
                        }
                        if (thumb != null)
                        {
                            var src = info.FinalBitmap.CreateImageSourceFromBitmap(vm.Item.ImageBytesCached, thumb._thumbWidth, thumb._thumbHeight);
                            info.Callback(src);
                        }
                        doneAnything = true;
                    }
                }
                if (!doneAnything)
                {
                    Thread.Sleep(30);
                }
            }
        }

        public void MarkThumbDirty()
        {
            if (_vm != null)
            {
                _vm.Dirty = true;
            }
        }

        public void MarkThumbImageDirty()
        {
            if (_vm != null)
            {
                _vm.Item.ThumbnailCached = null;
                _vm.Dirty = true;
            }
        }

        public void Rotate(Rotation rotation, bool clockwise)
        {
            FileImageViewModel.RotateOrResizeDone += new EventHandler<ObjectEventArgs<FileImage>>(FileImageViewModel_RotateOrResizeDone);

            FileImageViewModel.Rotate(rotation, clockwise);
            //UpdateIfDirty(ThumbVisible, false);
        }

        void FileImageViewModel_RotateOrResizeDone(object sender, ObjectEventArgs<FileImage> e)
        {
            if (FileImageViewModel != null)
            {
                FileImageViewModel.RotateOrResizeDone -= FileImageViewModel_RotateOrResizeDone;
                FinishRotateOrResize();
            }
        }

        private void FinishRotateOrResize()
        {
            FileImageViewModel.ClearThumbnail();
            FileImageViewModel.ImageSource = null;
            FileImageViewModel.ClearFileBytes();
            FileImageViewModel.ClearBitmapCached();
            FileImageViewModel.Dirty = true; // owen added            
            ParentCollectionView.ForceRefresh = true;
            UpdateIfDirty(ThumbVisible, false);
            string thumbCache = FileImageViewModel.FileName.GetThumbFileName();
            if (File.Exists(thumbCache))
            {
                try
                {
                    File.SetAttributes(thumbCache, FileAttributes.Normal);
                    File.Delete(thumbCache);
                }
                catch { }
            }

            FileImageViewModel.Item.ClearImageInfo();
            FileImageViewModel.Item.ClearSize();
            FileImageViewModel.RaisePropertyChanged(null);
            SetThumb(FileImageViewModel.Item);
        }

        public void Resize(int width, int height)
        {
            FileImageViewModel.Resize(width, height);
        }

        public void ResizeDelete(int width, int height, ResizeInfo resizeInfo)
        {
            FileImageViewModel.RotateOrResizeDone += new EventHandler<ObjectEventArgs<FileImage>>(FileImageViewModel_RotateOrResizeDone);
            FileImageViewModel.ResizeDelete(width, height, resizeInfo);
        }

        public void RotateCounterclockwise()
        {
            _parentCollectionView.ThumbsHandler.WantRotateSelectedCounterClockwise(this);
        }

        public void RotateClockwise()
        {
            _parentCollectionView.ThumbsHandler.WantRotateSelectedClockwise(this);
        }

        public void ResizeCommandTriggered(int width, int height)
        {
            _parentCollectionView.ThumbsHandler.WantResize(this, width, height);
        }

        public void ResizeDeleteCommandTriggered(int width, int height)
        {
            _parentCollectionView.ThumbsHandler.WantResizeDelete(this, width, height);
        }

        public bool WantCompare
        {
            get { return FileImageViewModel.WantCompare; }
            set { FileImageViewModel.WantCompare = value; }
        }

        public ImageCollectionView ParentCollectionView
        {
            get { return _parentCollectionView; }
            set { _parentCollectionView = value; }
        }

        public bool ThumbVisible
        {
            get { return _vm == null ? false : _vm.ThumbVisible; }
            set
            {
                if (_vm != null)
                {
                    if (_vm.ThumbVisible != value)
                    {
                        _vm.Dirty = true;

                        if (value && _vm != null)
                        {
                            if (ThumbDebug == null && Settings.Values.ShowDebugOnThumbs)
                            {
                                CreateThumbDebug();
                            }
                        }
                        else if (!value)
                        {
                            _LastVisible = DateTime.Now;
                        }
                        _vm.ThumbVisible = value;
                        _vm.Visible = value;

                        if (value)
                        {
                            UpdateDisplayBasedOnDisplayingGroups();
                        }
                        OnPropertyChanged("ThumbVisible");

                        ThumbVisibilityChanged.RaiseEvent(this);
                    }

                    _vm.ThumbVisible = value;
                    _vm.Visible = value;
                }
            }
        }

        void btnImage_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (e.ClickCount == 2)
            {
                if (_wantView != null)
                {
                    _wantView.Raise(this, new ObjectEventArgs<FileImageViewModel>(FileImageViewModel));
                }

                e.Handled = true;
            }
            else
            {
                PointMouseDown = e.GetPosition(Window1.MainWindow);
                e.Handled = true;
            }
        }

        void commandBar_RequestResize(object sender, ObjectEventArgsNonRef<FileImageViewModel, bool> e)
        {
            RequestResize.RaiseEvent(this, e.obj1, e.obj2);
        }

        void commandBar_RequestRotate(object sender, ObjectEventArgsNonRef<RotationParams, bool> e)
        {
            RequestRotate.RaiseEvent(this, e.obj1, e.obj2);
        }

        void commandBar_RequestResizeDelete(object sender, ObjectEventArgsNonRef<FileImageViewModel, bool> e)
        {
            RequestResizeDelete.RaiseEvent(this, e.obj1, e.obj2);
        }

        void commandBar_RequestDelete(object sender, ObjectEventArgsNonRef<FileImageViewModel, bool> e)
        {
            RequestDelete.RaiseEvent(this, e.obj1, e.obj2);
        }

        private void CreateThumbDebug()
        {
            ThumbDebug = new ThumbViewDebug();
            ThumbDebug.SetValue(Grid.RowProperty, 0);
            ThumbDebug.HorizontalAlignment = HorizontalAlignment.Stretch;
            ThumbDebug.VerticalAlignment = VerticalAlignment.Top;
            ThumbDebug.SetValue(Canvas.ZIndexProperty, 9999);
            ThumbDebug.Name = "thumbDebug";
            ThumbDebug.VerticalAlignment = VerticalAlignment.Top;
            ThumbDebug.Margin = new Thickness(2, 2, 0, 2);
            Binding b = new Binding();
            ThumbDebug.SetBinding(ThumbViewDebug.FileImageViewModelProperty, b);
            gridMain.Children.Add(ThumbDebug);
        }

        public ThumbnailView()
        {
            InitializeComponent();
        }


        public UpdateAction UpdateIfDirty(bool vis, bool skip)
        {
            if (_vm == null)
                return UpdateAction.None;

            if (!skip && !vis)
            {
                // outside visual viewing area
                return _vm.UpdateIfDirty(vis, skip);
            }
            else
            {
                return _vm.UpdateIfDirty(vis, skip);
            }
        }

        public void SetThumb(Bitmap bm)
        {
            if (_vm.ThumbImageSourceCached == null || _vm.ThumbImageSourceCachedDirty)
            {
                PassedInfoToCreateImageSource info = new PassedInfoToCreateImageSource(this, bm, src =>
                {
                    Dispatcher.BeginInvoke(() =>
                    {
                        if (_vm != null)
                        {
                            _vm.ThumbImageSourceCached = src;
                            SetFileNamePosition();
                            _vm.RaisePropertyChanged("ThumbImageSourceCached");
                        }
                        else
                        {
                            Debug.WriteLine("_vm was null");
                        }
                    }, DispatcherPriority.Send);
                });

                WorkQueue.Enqueue(info);
            }
        }

        public void SetThumb(FileImage fi)
        {
            var thumb = fi.ThumbnailCached;

            if (thumb == null)
            {
                if (fi.ThumbnailObject != null)
                {
                    fi.ThumbnailObject.SetThumbnail(FileImage.ThumbnailProvider.CreateAndSetThumbnail(fi, fi.FileName));
                    //Dispatcher.BeginInvoke(() =>
                    //{
                    //    if (fi.ThumbnailObject != null)
                    //    {
                    //        // fi.ThumbnailObject.SetThumbnail(FileImage.ThumbnailProvider.CreateAndSetThumbnail(fi, fi.FileName));
                    //        if (_vm != null && _vm.ThumbImageSourceCached == null)
                    //        {
                    //            _vm.ThumbImageSourceCached = fi.ThumbnailCached.CreateImageSourceFromBitmap(fi.ImageBytesCached, fi.ThumbnailObject._thumbWidth, fi.ThumbnailObject._thumbHeight);
                    //            SetFileNamePosition();
                    //            _vm.RaisePropertyChanged("ThumbImageSourceCached");
                    //        }
                    //    }
                    //}, DispatcherPriority.Normal); // .Background

                    if (fi.ThumbnailObject != null && (_vm != null && _vm.ThumbImageSourceCached == null))
                    {
                        Dispatcher.BeginInvoke(() =>
                        {
                            if (fi.ThumbnailObject != null && (_vm != null && _vm.ThumbImageSourceCached == null))
                            {
                                _vm.ThumbImageSourceCached = fi.ThumbnailCached.CreateImageSourceFromBitmap(fi.ImageBytesCached, fi.ThumbnailObject._thumbWidth, fi.ThumbnailObject._thumbHeight);
                                SetFileNamePosition();
                                _vm.RaisePropertyChanged("ThumbImageSourceCached");
                            }
                        }, DispatcherPriority.Normal); // .Background
                    }
                }
                return;
            }

            FinishMakeVisible(thumb);
        }

        private void FinishMakeVisible(Bitmap thumb)
        {
            if (thumb != null)
            {
                SetThumb(thumb);

                if (_tb != null)
                {
                    _tb.Visibility = Visibility.Collapsed;
                }
            }
            else
            {
                Dispatcher.RunOnDispatcher(new VoidDelegate(() =>
                {
                    try
                    {
                        if (_tb == null)
                        {
                            _tb = new TextBlock()
                            {
                                Text = "Unable to load " + _vm.FileNameOnly,
                                Visibility = Visibility.Visible,
                                HorizontalAlignment = HorizontalAlignment.Center,
                                VerticalAlignment = VerticalAlignment.Center
                            };
                            _tb.SetValue(Grid.RowSpanProperty, 4);
                            _tb.SetValue(Grid.ColumnSpanProperty, 2);
                            gridMain.Children.Add(_tb);
                        }
                        else
                        {
                            _tb.Visibility = Visibility.Visible;
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.ToString());
                    }
                }), DispatcherPriority.Normal);
            }
        }

        public void SetFileNamePosition()
        {
            if (imgMain == null)
                return;

            if (!Settings.Values.EvenThumbWidths)
            {
                if (imgMain.ActualWidth == 0D)
                {
                    imgMain.SizeChanged += new SizeChangedEventHandler(imgMain_SizeChanged);
                }
                else
                {
                    if (this.Width != Settings.Values.ThumbWidth)
                    {
                        this.Width = Settings.Values.ThumbWidth;
                    }
                }

                if (imgMain.HorizontalAlignment != HorizontalAlignment.Left)
                {
                    imgMain.HorizontalAlignment = HorizontalAlignment.Left;
                }
            }
            else
            {
                if (imgMain.HorizontalAlignment != HorizontalAlignment.Center)
                {
                    imgMain.HorizontalAlignment = HorizontalAlignment.Center;
                }
            }

            if (Settings.Values.ShowImageInfoBelowThumbs)
            {
                if (gridMain.RowDefinitions.Count == 3)
                {
                    RowDefinition def = new RowDefinition() { Height = new GridLength(20D) };
                    gridMain.RowDefinitions.Add(def);
                }
                if (gridMain.RowDefinitions[3].Height.Value != 20D)
                {
                    gridMain.RowDefinitions[3].Height = new GridLength(20D);
                }

                ThumbViewBottom.SetValue(Grid.RowProperty, 3);
            }
            else
            {
                if (gridMain.RowDefinitions.Count == 4)
                {
                    gridMain.RowDefinitions.RemoveAt(3);
                }
                //if (gridMain.RowDefinitions[3].Height.Value != 0D)
                //{
                //    gridMain.RowDefinitions[3].Height = new GridLength(0D);
                //}

                ThumbViewBottom.SetValue(Grid.RowProperty, 2);
            }
        }

        private void imgMain_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            imgMain.SizeChanged -= imgMain_SizeChanged;

            if (!Settings.Values.EvenThumbWidths)
            {
                double wid = imgMain.ActualWidth;
                this.Width = wid + 16D;
            }
            else
            {
                if (this.Width != Settings.Values.ThumbWidth)
                {
                    this.Width = Settings.Values.ThumbWidth;
                }
            }
        }

        private void btnImage_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (_wantView != null)
            {
                _wantView.Raise(this, new ObjectEventArgs<FileImageViewModel>(FileImageViewModel));
            }

            e.Handled = true;
        }

        public void DeleteImage()
        {
            _parentCollectionView.ThumbsHandler.WantDeleteSelected(this);
        }

        private void UserControl_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Delete)
            {
                RequestDelete.RaiseEvent(this, FileImageViewModel, false);
                e.Handled = true;
            }
            else if (e.Key == Key.OemMinus)
            {
                _parentCollectionView.ThumbsHandler.WantResizeDelete(this, _vm.LastOriginalBitmapWidth, _vm.LastOriginalBitmapHeight);
                e.Handled = true;
            }
            if (e.Key == Key.Q)
            {
                _parentCollectionView.ThumbsHandler.WantRotateSelectedCounterClockwise(this);
                e.Handled = true;
            }
            else if (e.Key == Key.W)
            {
                _parentCollectionView.ThumbsHandler.WantRotateSelectedClockwise(this);
                e.Handled = true;
            }            
        }

        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChanged.RaiseEvent(this, propertyName);
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        private void ThumbViewBottom_Loaded(object sender, RoutedEventArgs e)
        {
            ThumbViewBottom.ThumbnailView = this;
        }

        //public bool? GetIsVisibleInScroller(ScrollViewer scrollViewer, double viewportWidth, double viewportHeight, double verticalOffset)
        //{
        //    if (this.Parent == null)
        //    {
        //        return false;
        //    }
        //    return UtilWPF.GetIsVisibleInScroller(this, scrollViewer, viewportWidth, viewportHeight, verticalOffset);
        //}

        #region IVirtualizedCreated Members

        public void OnBeingCreated(int childIndex, VirtualizingTilePanel parentPanel, object parent, bool initial)
        {
            _parentCollectionView = (parent as ImageCollectionView);
            if (_parentCollectionView != null && this._vm != null)
            {
                if (this._vm == _parentCollectionView._lastSelected)
                {
                    var lbi = BrainTechLLC.WPF.TempExten.FindParent<ListBoxItem>(this);
                    if (!lbi.IsFocused || initial)
                    {
                        Dispatcher.BeginInvoke(() => lbi.Focus());
                    }
                }
                UpdateDisplayBasedOnDisplayingGroups();
            }
        }

        public void OnBeingDestroyed(int itemIndex, VirtualizingTilePanel parentPanel)
        {
            // Console.WriteLine("Destroyed " + itemIndex.ToString());            
            if (_vm != null)
            {
                ThumbVisible = false;
                if (_parentCollectionView != null && _parentCollectionView.ThumbsHandler != null)
                {
                    _parentCollectionView.ThumbsHandler._thumbsByFileName.Remove(this._vm.FileName);
                }
                this.UpdateIfDirty(ThumbVisible, false);
                this.FileImageViewModel = null;
            }
        }

        #endregion

        private void btnImage_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            System.Windows.Point pointNow = e.GetPosition(Window1.MainWindow);
            if (Math.Abs(PointMouseDown.X - pointNow.X) < 100 && Math.Abs(PointMouseDown.Y - pointNow.Y) < 100)
            {
                BrainTechLLC.WPF.TempExten.FindParent<ListBoxItem>(this).Focus();

                if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
                {
                    _parentCollectionView.ToggleSelection(FileImageViewModel, true);
                }
                else if ((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift)
                {
                    if (ParentCollectionView._lastSelected != null)
                    {
                        int index = ParentCollectionView.IndexOf(ParentCollectionView._lastSelected);
                        int otherIndex = ParentCollectionView.IndexOf(FileImageViewModel);
                        ParentCollectionView.SelectAndMoveTo(index, otherIndex, Keyboard.Modifiers);
                    }
                }
                else
                {
                    _parentCollectionView.ClearSelected();
                    _parentCollectionView.ToggleSelection(FileImageViewModel, true);
                }

                e.Handled = true;
            }
        }
    }

    public class PassedInfoToCreateImageSource
    {
        public ThumbnailView ThumbnailView;
        public Bitmap FinalBitmap;
        public Action<ImageSource> Callback;

        public PassedInfoToCreateImageSource(ThumbnailView thumbnailView, Bitmap finalBitmap, Action<ImageSource> callback)
        {
            Callback = callback;
            ThumbnailView = thumbnailView;
            FinalBitmap = finalBitmap;
        }
    }

}
